package com.znwxss.utils;

import com.qiniu.common.QiniuException;
import com.qiniu.storage.BucketManager;
import com.qiniu.storage.UploadManager;
import com.qiniu.storage.model.FileInfo;

import com.qiniu.util.Auth;
import com.znwxss.config.QiNiuYunConfig;
import com.znwxss.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;
import com.znwxss.constants.HttpStatus;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;


/**
 * 七牛云工具类
 * @Author: hb
 * @CreateTime: 2023-11-02 23:38
 * @Version: 1.0
 */
@Slf4j
@Component
public class OssUploadUtils {

    private final QiNiuYunConfig qiNiuYunConfig;
    private final Auth auth;
    private final UploadManager uploadManager;
    private final BucketManager bucketManager;

    @Autowired
    public OssUploadUtils(QiNiuYunConfig qiNiuYunConfig, Auth auth, UploadManager uploadManager, BucketManager bucketManager) {
        this.qiNiuYunConfig = qiNiuYunConfig;
        this.auth = auth;
        this.uploadManager = uploadManager;
        this.bucketManager = bucketManager;
    }

    /**
     * 批量上传图片
     *
     * @param multipartFiles
     * @return
     */
    public List<String> uploadImages(MultipartFile[] multipartFiles, Integer type) {
        List<String> imageUrlList = new ArrayList<>();
        for (MultipartFile file : multipartFiles) {
            imageUrlList.add(upload(file, type));
        }
        return imageUrlList;
    }




    /**
     * 上传图片
     *
     * @param multipartFile
     * @return
     */
    public String upload(MultipartFile multipartFile, Integer type) {
        //检查文件是否为合法
//        uploadImageCheckUtil(multipartFile);
        try {

            //1、获取文件上传的流
            byte[] fileBytes = multipartFile.getBytes();
            //2、创建日期目录分隔
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd");
            String datePath = dateFormat.format(new Date());

            //3、获取文件名
            String originalFilename = multipartFile.getOriginalFilename();
            String suffix = originalFilename.substring(originalFilename.lastIndexOf("."));
            String filename = datePath + "/" + UUID.randomUUID().toString().replace("-", "") + suffix;

            //5.获取七牛云提供的 token
            String upToken = auth.uploadToken(qiNiuYunConfig.getBucketName());
            uploadManager.put(fileBytes, filename, upToken);

            return qiNiuYunConfig.getUrl() +"/"+ filename;

        } catch (IOException e) {
            throw new BusinessException(HttpStatus.ERROR, "上传异常");
        }
    }

    /**
     * 批量删除图片
     *
     * @param images
     * @return
     */
    @Async("taskExecutor")
    public void deleteImages(List<String> images) {
        images.stream().forEach(this::deleteFile);
    }


    /**
     * 图片上传判断工具
     *
     * @return
     */
    public void uploadImageCheckUtil(MultipartFile file) {
        try {
            InputStream inputStream = file.getInputStream();
            BufferedImage image = ImageIO.read(inputStream);
            if (image == null) {
                throw new BusinessException(HttpStatus.ERROR, "该图片非图片!");
            }
        } catch (IOException e) {
            log.error("上传发生异常 : {}", e.getMessage());
            throw new BusinessException(HttpStatus.ERROR, "上传失败!");
        }
    }

    /**
     * @param url
     * @return 删除图片
     * @throws RuntimeException
     */
    @Async("taskExecutor")
    public Boolean deleteFile(String url) {

        url = StringUtils.substringAfter(url, qiNiuYunConfig.getUrl() + "/");

        if (Objects.isNull(checkFile(url))) {
            return true;
        }

        try {
            bucketManager.delete(qiNiuYunConfig.getBucketName(), url);

        } catch (QiniuException e) {
            throw new BusinessException(HttpStatus.ERROR, "删除失败!");
        }
        return true;
    }

    /**
     * 删除前检查文件
     *
     * @param key
     * @return
     */
    public FileInfo checkFile(String key) {
        FileInfo fileInfo = null;
        try {
            fileInfo = bucketManager.stat(qiNiuYunConfig.getBucketName(), key);
        } catch (QiniuException ignored) {
            throw new BusinessException(HttpStatus.ERROR, "存储异常!");
        }
        return fileInfo;
    }

    /**
     * 通过发送http get 请求获取文件资源
     * @param
     * @return
     */
    public byte[] downloadByte(String targetUrl) {
        // 获取文件下载路径
        String url = auth.privateDownloadUrl(targetUrl);
        RestTemplate restTemplate = new RestTemplate();

        // 设置请求头
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        HttpEntity<String> entity = new HttpEntity<>(headers);

        // 发送 GET 请求并获取响应
        ResponseEntity<byte[]> response = restTemplate.exchange(url, HttpMethod.GET, entity, byte[].class);
        if (response.getStatusCode() == org.springframework.http.HttpStatus.OK) {
            return response.getBody();
        } else {
            System.out.println("Unexpected code " + response.getStatusCodeValue());
            return new byte[0];
        }
    }


    /**
     * 读取字节输入流内容
     * @param is
     * @return
     */
    public byte[] readInputStream(InputStream is) {
        ByteArrayOutputStream writer = new ByteArrayOutputStream();
        byte[] buff = new byte[1024 * 2];
        int len = 0;
        try {
            while((len = is.read(buff)) != -1) {
                writer.write(buff, 0, len);
            }
            is.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return writer.toByteArray();
    }
}
